2. Grilla de estimación

Nuestro objetivo es determinar el volumen espacial que sera el limite de nuestro modelo de recursos. Es decir, no estimaremos mas allá de los limites representados por esta caja.

Logo de Jupyter en la carpeta img

Nuestro punto de partida sera la base de datos compositada a 6 metros, en donde los valores -99 han sido ya filtrados.

2.1. Simplificacion de base de datos compositada

[12]:
## Cargar datos ya compositados y con UGs del capitulo anterior

import pandas as pd
import numpy as np

# Cargar base de datos en pandas
df_original = pd.read_csv('Data_compositada_con_UGs.csv', sep=',', encoding='latin1')
df_original
[12]:
cu_pct UG dhid from to SURV_X SURV_Y SURV_Z
0 0.020300 2.0 98CCD089 12.2 18.2 472187.343570 6.925806e+06 4211.772172
1 0.009500 2.0 98CCD089 18.2 24.2 472187.740701 6.925807e+06 4205.844155
2 0.006767 2.0 98CCD089 24.2 30.2 472188.089349 6.925807e+06 4199.915106
3 0.010433 2.0 98CCD089 30.2 36.2 472188.470072 6.925808e+06 4193.995578
4 0.011133 2.0 98CCD089 36.2 42.2 472188.878860 6.925809e+06 4188.084383
... ... ... ... ... ... ... ... ...
16877 0.095000 4.0 CCDDH-007 450.0 456.0 471922.691912 6.925392e+06 4022.517796
16878 0.109000 4.0 CCDDH-007 456.0 462.0 471924.631624 6.925395e+06 4017.651413
16879 0.179667 4.0 CCDDH-007 462.0 468.0 471926.586648 6.925397e+06 4012.784519
16880 0.148333 4.0 CCDDH-007 468.0 474.0 471928.548677 6.925400e+06 4007.918137
16881 0.206000 4.0 CCDDH-007 474.0 480.0 471930.530423 6.925403e+06 4003.054819

16882 rows × 8 columns

Limpiaremos la base de datos para simplificar la notación, asi como para mantener solo las columnas correspondiente a las coordenadas, variable de interés y Unidades Geológicas.

[13]:
# Limpiar la base de datos: mantener solo las columnas especificadas y renombrar
df = df_original[['SURV_X', 'SURV_Y', 'SURV_Z', 'cu_pct', 'UG']].copy()

# Renombrar las columnas de coordenadas
df = df.rename(columns={
    'SURV_X': 'X',
    'SURV_Y': 'Y',
    'SURV_Z': 'Z'
})

# exportamos base de datos limpia
df.to_csv('data.csv', index=False)

df
[13]:
X Y Z cu_pct UG
0 472187.343570 6.925806e+06 4211.772172 0.020300 2.0
1 472187.740701 6.925807e+06 4205.844155 0.009500 2.0
2 472188.089349 6.925807e+06 4199.915106 0.006767 2.0
3 472188.470072 6.925808e+06 4193.995578 0.010433 2.0
4 472188.878860 6.925809e+06 4188.084383 0.011133 2.0
... ... ... ... ... ...
16877 471922.691912 6.925392e+06 4022.517796 0.095000 4.0
16878 471924.631624 6.925395e+06 4017.651413 0.109000 4.0
16879 471926.586648 6.925397e+06 4012.784519 0.179667 4.0
16880 471928.548677 6.925400e+06 4007.918137 0.148333 4.0
16881 471930.530423 6.925403e+06 4003.054819 0.206000 4.0

16882 rows × 5 columns

2.2. Determinación de parámetros de la grilla

Para lo que sigue, sera necesario saber con exactitud los limites de nuestro modelo de bloques, dado un tamaño de bloque fijo. Para esto, definimos que el tamaño de cada de bloque sera de 15 metros x 15 metros x 15 metros (largo x ancho x alto o bien incremento en el eje X, incremento en el eje Y e incremento en el eje Z).

Logo de Jupyter en la carpeta img

Los limites preliminares los podemos encontrar inspeccionando nuestros datos, buscando aquel más alto, aquel más bajo, el más al oeste y el más al este, e igualmente en la norte-sur.

[14]:
xmin = df['X'].min()
xmax = df['X'].max()
ymin = df['Y'].min()
ymax = df['Y'].max()
zmin = df['Z'].min()
zmax = df['Z'].max()

print(f"Xmin: {xmin:.2f}, Xmax: {xmax:.2f}")
print(f"Ymin: {ymin:.2f}, Ymax: {ymax:.2f}")
print(f"Zmin: {zmin:.2f}, Zmax: {zmax:.2f}")
Xmin: 471116.24, Xmax: 473023.89
Ymin: 6924721.57, Ymax: 6926164.63
Zmin: 2950.02, Zmax: 4445.78

En base a estos limites y el tamaño definido para cada bloque, podemos encontrar el numero de bloques en cada dirección y el tamaño total de nuestra grilla.

[15]:
block_size_x = 15  # Tamaño del bloque en X (metros)
block_size_y = 15  # Tamaño del bloque en Y (metros)
block_size_z = 15  # Tamaño del bloque en Z (metros)

Nx = int((xmax - xmin) / block_size_x) + 1
Ny = int((ymax - ymin) / block_size_y) + 1
Nz = int((zmax - zmin) / block_size_z) + 1

print(f"Número de bloques en X: {Nx}")
print(f"Número de bloques en Y: {Ny}")
print(f"Número de bloques en Z: {Nz}")

grid_size_x = Nx * block_size_x
grid_size_y = Ny * block_size_y
grid_size_z = Nz * block_size_z

print(f"Tamaño total de la grilla en X: {grid_size_x} metros")
print(f"Tamaño total de la grilla en Y: {grid_size_y} metros")
print(f"Tamaño total de la grilla en Z: {grid_size_z} metros")

print(f"Dimensiones de la grilla de estimación: {Nx} x {Ny} x {Nz} bloques")
print(f"Tamaño total de la grilla: Nx*Ny*Nz = {Nx * Ny * Nz} bloques")

Número de bloques en X: 128
Número de bloques en Y: 97
Número de bloques en Z: 100
Tamaño total de la grilla en X: 1920 metros
Tamaño total de la grilla en Y: 1455 metros
Tamaño total de la grilla en Z: 1500 metros
Dimensiones de la grilla de estimación: 128 x 97 x 100 bloques
Tamaño total de la grilla: Nx*Ny*Nz = 1241600 bloques

Nota: Anotamos estos parámetros ya que recurrimos a estos números constantemente en los flujos de trabajo posteriores

[16]:
# imprimir parámetros en formato GSLIB
# 50   0.5    1.0                  -nx,xmn,xsiz
# 50   0.5    1.0                  -ny,ymn,ysiz
# 1    0.5    1.0                  -nz,zmn,zsiz

print(f"{Nx}   {xmin:.2f}    {block_size_x:.0f}\t\t\t-nx,xmn,xsiz")
print(f"{Ny}   {ymin:.2f}    {block_size_y:.0f}\t\t\t-ny,ymn,ysiz")
print(f"{Nz}   {zmin:.2f}    {block_size_z:.0f}\t\t\t-nz,zmn,zsiz")
128   471116.24    15                   -nx,xmn,xsiz
97   6924721.57    15                   -ny,ymn,ysiz
100   2950.02    15                     -nz,zmn,zsiz

Como hemos calculado, nuestro modelo tendrá un total de 1.241.600 de bloques, lo que corresponde a un modelo dentro del estándar de la industria, considerando los números que se manejan allí. Este numero de información, sin embargo, no puede ser manejado por la mayoría de los softwares de oficina como Excel, por lo que tendremos que recurrir a otro tipo de herramientas para el manejo de estos datos.

2.3. Visualizacion de los limites de la grilla

Procedemos a visualizar los limites de nuestro modelo de bloques junto con las muestras para verificación.

[33]:
continuous = 'cu_pct'

import plotly.io as pio
# pio.renderers.default = "colab"
pio.renderers.default = "notebook" # usar esta linea en jupyter notebook o vscode
import plotly.graph_objects as go
import plotly.express as px
import plotly.offline as py

fig = go.Figure(data=[go.Scatter3d(
    x=df['X'],
    y=df['Y'],
    z=df['Z'],
    marker=dict(color=df[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=df[continuous].quantile(0.95),
                size=2.0, # Esta opcion controla el tamaño de los datos
                colorbar=dict(
                    title='Cu [%]',
                    thickness=20,
                    # Add a border to the colorbar
                    outlinecolor='black',  # Color of the border
                    outlinewidth=2,       # Width of the border
                    bordercolor='white',   # Background border color (if applicable)
                    borderwidth=1         # Background border width
                )
                ),
    mode='markers',
    opacity=1
)])

# otras opciones para controlar el color de los elementos de la figura, borrar hovermode para desactivar etiquetas al pasar el mouse
fig.update_layout(scene = dict(
                    xaxis = dict(
                        title='Este',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white",),
                    yaxis = dict(
                        title='Norte',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white"),
                    zaxis = dict(
                        title='Elevación',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white",),
                    ),
                    font_family="Times New Roman",
                    font_color="black", hovermode=False
                  )

# Definir los vértices del cubo
cube_x = [xmin, xmax, xmax, xmin, xmin, xmax, xmax, xmin]
cube_y = [ymin, ymin, ymax, ymax, ymin, ymin, ymax, ymax]
cube_z = [zmin, zmin, zmin, zmin, zmax, zmax, zmax, zmax]

# Añadir aristas (wireframe) para mejor visualización
edge_pairs = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)]
edge_x, edge_y, edge_z = [], [], []
for a, b in edge_pairs:
    edge_x += [cube_x[a], cube_x[b], None]
    edge_y += [cube_y[a], cube_y[b], None]
    edge_z += [cube_z[a], cube_z[b], None]

# Añadir las aristas a la figura sin leyenda ni colorbar ni hoverinfo ni otros elementos
fig.add_trace(go.Scatter3d(
    x=edge_x,
    y=edge_y,
    z=edge_z,
    mode='lines',
    line=dict(color='black', width=2),
    showlegend=False,
    hoverinfo='skip'
))

# ocultar la leyenda/autonombre "trace 0" junto al colorbar
fig.update_layout(showlegend=False)

fig.show()